// bounce_adam implementation
// Copyright 2006 (C) Ralph Thomas

#include <view/bounce_adam.h>
#include <binder.hpp>
#include <boost/bind.hpp>

namespace view {
	struct connection_t {
		adobe::binder_helper_t	helper_m;
		adobe::name_t			name_m;
		adobe::sheet_t&			sheet_m;
		adobe::value_t			last_m;
		adobe::value_t			pump_m;
		adobe::sheet_t::connection_t connection;

		void initialize()
		{
			connection = sheet_m.monitor_value(name_m, boost::bind(&connection_t::update_binder, this, _1));
			helper_m.initialize(pump_m, boost::bind(&connection_t::update_sheet, this, _1), 0);
		}

		void update_sheet(const adobe::value_t& val)
		{
			if( last_m == val ) return;
			last_m = val;
			sheet_m.set(name_m, val);
			sheet_m.update();
		}

		void update_binder(const adobe::value_t& val)
		{
			if( last_m == val ) return;
			last_m = val;
			helper_m.set(val);
		}

		connection_t( const adobe::value_t& pump, const adobe::name_t& name, adobe::sheet_t& sheet, const adobe::factory_token_t& token)
		 : helper_m(sheet), name_m(name), sheet_m(sheet), pump_m(pump)
		{
			boost::function<void()> fn(boost::bind(&connection_t::initialize, this));
			token.show_window_signal_m.connect(fn);
		}

		~connection_t()
		{
			connection.disconnect();
		}
	};
	adobe::widget_node_t bounce_adam_factory(
		const adobe::dictionary_t&		parameters,
		const adobe::widget_node_t&		parent,
		const adobe::factory_token_t&	token)
	{
		adobe::dictionary_t::const_iterator i(parameters.begin());
		while (i != parameters.end()) {
			connection_t* c = new connection_t(i->second, i->first, token.sheet_m, token);
			token.assemblage_m.delete_on_destruction( c );
			i++;
		}
		return parent;
	}
}
